上一篇分析了广播的注册流程,这篇来分析下广播的发送、处理流程。这里为什么把发送和处理和来一起说咧,那是因为其实这是一个过程,发送接口里面差不多就是处理过程了。我们先照例把相关代码位置啰嗦一下(4.2.2):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| frameworks/base/core/java/android/app/ContextImpl.java frameworks/base/core/java/android/app/LoadedApk.java frameworks/base/core/java/android/app/ActivityThread.java frameworks/base/core/java/android/content/Intent.java frameworks/base/core/java/android/content/IntentFilter.java frameworks/base/core/java/android/content/BroadcastReceiver.java frameworks/base/core/java/android/content/IIntentReceiver.aidl frameworks/base/services/java/com/android/server/IntentResolver.java frameworks/base/services/java/com/android/server/am/ActivityManagerService.java frameworks/base/services/java/com/android/server/am/RecevierList.java frameworks/base/services/java/com/android/server/am/BroadcastQueue.java frameworks/base/services/java/com/android/server/am/BroadcastFilter.java frameworks/base/services/java/com/android/server/am/BroadcastRecord.java frameworks/base/services/java/com/android/server/pm/PackageManagerService.java
|
然后把处理流程贴张图:
(这个图很夸张吧,拉一下本篇的滚动条就知道为啥这么夸张了;本来想分情况画几张的,画到后面还是合在一起了)
发送接口
应用接口
普通应用发送广播的接口和注册篇注册的一样,都在 Context 里面,但是实现在 ContextImpl 里面:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| @Override public void sendBroadcast(Intent intent) { warnIfCallingFromSystemProcess(); String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); try { intent.setAllowFds(false); ActivityManagerNative.getDefault().broadcastIntent( mMainThread.getApplicationThread(), intent, resolvedType, null, Activity.RESULT_OK, null, null, null, false, false, getUserId()); } catch (RemoteException e) { } }
|
这里我们看最简单,也是最常见的那种,直接一个 Intent 发出去的。其实最后是调用到 AMS 里面的同名接口(前面一篇说过了,广播的处理是在 AMS 中的):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| public final int broadcastIntent(IApplicationThread caller, Intent intent, String resolvedType, IIntentReceiver resultTo, int resultCode, String resultData, Bundle map, String requiredPermission, boolean serialized, boolean sticky, int userId) { enforceNotIsolatedCaller("broadcastIntent"); synchronized(this) { intent = verifyBroadcastLocked(intent); final ProcessRecord callerApp = getRecordForAppLocked(caller); final int callingPid = Binder.getCallingPid(); final int callingUid = Binder.getCallingUid(); final long origId = Binder.clearCallingIdentity(); int res = broadcastIntentLocked(callerApp, callerApp != null ? callerApp.info.packageName : null, intent, resolvedType, resultTo, resultCode, resultData, map, requiredPermission, serialized, sticky, callingPid, callingUid, userId); Binder.restoreCallingIdentity(origId); return res; } }
|
AMS 里面的这个接口,有一个 boolean 参数 serialized(还有个 sticky 的,我们不管这个 stciky)。true 的话,表示发送的串行广播,false 表示发送并行广播。串行广播就是说,一个广播来了,有一对接收器, AMS 会等前一个执行完,才会发给下一个处理,接收器处理广播是一个接着一个处理的。并行的就是 AMS 把广播发给一个接收器之后,会马上返回,然后再发给下一个,直到发送完,接收器处理广播是并行的(同时处理)。用简单参数的接口,默认发送的是并行广播。
回到接口上,加了多线程互斥锁之后,调用 broadcastIntentLocked 处理。这个函数就是看名字是发送广播(Intent),其实就是处理过程,而且非常长,我们发到后面慢慢说。
系统发送接口
我们来看看系统是怎么发送的。我们以前面说的 BOOT_COMPLETED 广播来看。这个广播是 AMS 中发出来的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| final void finishBooting() { IntentFilter pkgFilter = new IntentFilter(); pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART); pkgFilter.addDataScheme("package"); ... ... synchronized (this) { ... ... if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) { Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG); mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY); SystemProperties.set("sys.boot_completed", "1"); SystemProperties.set("dev.bootcomplete", "1"); for (int i=0; i<mStartedUsers.size(); i++) { UserStartedState uss = mStartedUsers.valueAt(i); if (uss.mState == UserStartedState.STATE_BOOTING) { uss.mState = UserStartedState.STATE_RUNNING; final int userId = mStartedUsers.keyAt(i); Intent intent = new Intent(Intent.ACTION_BOOT_COMPLETED, null); intent.putExtra(Intent.EXTRA_USER_HANDLE, userId); broadcastIntentLocked(null, null, intent, null, null, 0, null, null, android.Manifest.permission.RECEIVE_BOOT_COMPLETED, false, false, MY_PID, Process.SYSTEM_UID, userId); } } } } }
|
AMS 里面自己发广播,直接调用 broadcastIntentLocked 了。估计其他系统服务里面还是调用 AMS 的 broadcastIntent 接口的吧。
接下来说下广播处理流程。AMS 中处理广播的流程就是 broadcastIntentLocked 这个函数,这个函数也是非常长的(差不多6、7百行),我们分段慢慢来(会跳过一些非重要的部分):
a. 收集广播接收器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
| private final int broadcastIntentLocked(ProcessRecord callerApp, String callerPackage, Intent intent, String resolvedType, IIntentReceiver resultTo, int resultCode, String resultData, Bundle map, String requiredPermission, boolean ordered, boolean sticky, int callingPid, int callingUid, int userId) { intent = new Intent(intent); intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES); if (DEBUG_BROADCAST_LIGHT) Slog.v( TAG, (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent + " ordered=" + ordered + " userid=" + userId); if ((resultTo != null) && !ordered) { Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!"); } userId = handleIncomingUser(callingPid, callingUid, userId, true, false, "broadcast", callerPackage); if (userId != UserHandle.USER_ALL && mStartedUsers.get(userId) == null) { if (callingUid != Process.SYSTEM_UID || (intent.getFlags() & Intent.FLAG_RECEIVER_BOOT_UPGRADE) == 0) { Slog.w(TAG, "Skipping broadcast of " + intent + ": user " + userId + " is stopped"); return ActivityManager.BROADCAST_SUCCESS; } } ... ... int[] users; if (userId == UserHandle.USER_ALL) { users = mStartedUserArray; } else { users = new int[] {userId}; } List receivers = null; List<BroadcastFilter> registeredReceivers = null; if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) { receivers = collectReceiverComponents(intent, resolvedType, users); } if (intent.getComponent() == null) { registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false, userId); } final boolean replacePending = (intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0; if (DEBUG_BROADCAST) Slog.v(TAG, "Enqueing broadcast: " + intent.getAction() + " replacePending=" + replacePending); ... ... return ActivityManager.BROADCAST_SUCCESS; }
|
一个广播发出来了,AMS 要做的第一步,首先是要找到有哪些接收器要接收这条广播。前面一篇说了,注册接收器有动态注册和静态注册2种。这里看代码果然也是分开2步来收集的。我们先来看收集静态的:
a.a 收集静态注册接收器
静态注册接收器收集由 collectReceiverComponents 处理:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| private List<ResolveInfo> collectReceiverComponents(Intent intent, String resolvedType, int[] users) { List<ResolveInfo> receivers = null; try { HashSet<ComponentName> singleUserReceivers = null; boolean scannedFirstReceivers = false; for (int user : users) { List<ResolveInfo> newReceivers = AppGlobals.getPackageManager() .queryIntentReceivers(intent, resolvedType, STOCK_PM_FLAGS, user); ... ... } } catch (RemoteException ex) { } return receivers; }
|
这个函数虽然有 100 多行,但是我们关心的只有调用 PM 的那句 queryIntentReceivers 而已。前面一篇说了,静态注册的广播数据保存在 PMS 中,所以这里要调用 PM 的接口去 PMS 里面去取。所以我去 PMS 里面去看看:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| @Override public List<ResolveInfo> queryIntentReceivers(Intent intent, String resolvedType, int flags, int userId) { if (!sUserManager.exists(userId)) return Collections.emptyList(); ComponentName comp = intent.getComponent(); if (comp == null) { if (intent.getSelector() != null) { intent = intent.getSelector(); comp = intent.getComponent(); } } if (comp != null) { List<ResolveInfo> list = new ArrayList<ResolveInfo>(1); ActivityInfo ai = getReceiverInfo(comp, flags, userId); if (ai != null) { ResolveInfo ri = new ResolveInfo(); ri.activityInfo = ai; list.add(ri); } return list; } synchronized (mPackages) { String pkgName = intent.getPackage(); if (pkgName == null) { return mReceivers.queryIntent(intent, resolvedType, flags, userId); } final PackageParser.Package pkg = mPackages.get(pkgName); if (pkg != null) { return mReceivers.queryIntentForPackage(intent, resolvedType, flags, pkg.receivers, userId); } return null; } }
|
我们在说之前先看看 ResolveInfo 这个东西,好歹返回的列表里面是这个东西:
1 2 3 4 5 6 7 8 9 10
| public class ResolveInfo implements Parcelable { ... ... }
|
里面的具体东西我们就不看了,看下注释,是说一个 ResolverInfo 对应一个 IntentFilter。然后就是 mReceivers 这个 ActivityIntentResolver,注册篇已经提及过了。PMS 中就是它保存了静态注册的接收器。
1 2 3 4 5 6 7 8 9
| public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags, int userId) { if (!sUserManager.exists(userId)) return null; mFlags = flags; return super.queryIntent(intent, resolvedType, (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId); }
|
我们去看父类(IntentResolver)的 queryIntent:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
| public List<R> queryIntent(Intent intent, String resolvedType, boolean defaultOnly, int userId) { String scheme = intent.getScheme(); ArrayList<R> finalList = new ArrayList<R>(); final boolean debug = localLOGV || ((intent.getFlags() & Intent.FLAG_DEBUG_LOG_RESOLUTION) != 0); if (debug) Slog.v( TAG, "Resolving type " + resolvedType + " scheme " + scheme + " of intent " + intent); F[] firstTypeCut = null; F[] secondTypeCut = null; F[] thirdTypeCut = null; F[] schemeCut = null; if (resolvedType != null) { int slashpos = resolvedType.indexOf('/'); if (slashpos > 0) { final String baseType = resolvedType.substring(0, slashpos); if (!baseType.equals("*")) { if (resolvedType.length() != slashpos+2 || resolvedType.charAt(slashpos+1) != '*') { firstTypeCut = mTypeToFilter.get(resolvedType); if (debug) Slog.v(TAG, "First type cut: " + firstTypeCut); secondTypeCut = mWildTypeToFilter.get(baseType); if (debug) Slog.v(TAG, "Second type cut: " + secondTypeCut); } else { firstTypeCut = mBaseTypeToFilter.get(baseType); if (debug) Slog.v(TAG, "First type cut: " + firstTypeCut); secondTypeCut = mWildTypeToFilter.get(baseType); if (debug) Slog.v(TAG, "Second type cut: " + secondTypeCut); } thirdTypeCut = mWildTypeToFilter.get("*"); if (debug) Slog.v(TAG, "Third type cut: " + thirdTypeCut); } else if (intent.getAction() != null) { firstTypeCut = mTypedActionToFilter.get(intent.getAction()); if (debug) Slog.v(TAG, "Typed Action list: " + firstTypeCut); } } } if (scheme != null) { schemeCut = mSchemeToFilter.get(scheme); if (debug) Slog.v(TAG, "Scheme list: " + schemeCut); } if (resolvedType == null && scheme == null && intent.getAction() != null) { firstTypeCut = mActionToFilter.get(intent.getAction()); if (debug) Slog.v(TAG, "Action list: " + firstTypeCut); } FastImmutableArraySet<String> categories = getFastIntentCategories(intent); if (firstTypeCut != null) { buildResolveList(intent, categories, debug, defaultOnly, resolvedType, scheme, firstTypeCut, finalList, userId); } if (secondTypeCut != null) { buildResolveList(intent, categories, debug, defaultOnly, resolvedType, scheme, secondTypeCut, finalList, userId); } if (thirdTypeCut != null) { buildResolveList(intent, categories, debug, defaultOnly, resolvedType, scheme, thirdTypeCut, finalList, userId); } if (schemeCut != null) { buildResolveList(intent, categories, debug, defaultOnly, resolvedType, scheme, schemeCut, finalList, userId); } sortResults(finalList); if (VALIDATE) { List<R> oldList = mOldResolver.queryIntent(intent, resolvedType, defaultOnly, userId); if (oldList.size() != finalList.size()) { ValidationFailure here = new ValidationFailure(); here.fillInStackTrace(); Log.wtf(TAG, "Query result " + intent + " size is " + finalList.size() + "; old implementation is " + oldList.size(), here); } } if (debug) { Slog.v(TAG, "Final result list:"); for (R r : finalList) { Slog.v(TAG, " " + r); } } return finalList; }
|
这个函数前面是通过传过来的 Intent 从 IntentResolver 那一堆保存注册接收器数据的列表中选出匹配的 F(PMS 中的静态注册的 F 是 PackageParser.ActivityIntentInfo),一般来说匹配条件就是注册广播中 IntentFilter 可以设置的那一堆条件了:MIME type、Scheme、Action 等等(到这里的都是隐式的,显式的前面直接给解析好了)。然后我们就得去看看 buildResolveList 这个函数是怎么构造 R 出来的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
| private void buildResolveList(Intent intent, FastImmutableArraySet<String> categories, boolean debug, boolean defaultOnly, String resolvedType, String scheme, F[] src, List<R> dest, int userId) { final String action = intent.getAction(); final Uri data = intent.getData(); final String packageName = intent.getPackage(); final boolean excludingStopped = intent.isExcludingStopped(); final int N = src != null ? src.length : 0; boolean hasNonDefaults = false; int i; F filter; for (i=0; i<N && (filter=src[i]) != null; i++) { int match; if (debug) Slog.v(TAG, "Matching against filter " + filter); if (excludingStopped && isFilterStopped(filter, userId)) { if (debug) { Slog.v(TAG, " Filter's target is stopped; skipping"); } continue; } if (packageName != null && !packageName.equals(packageForFilter(filter))) { if (debug) { Slog.v(TAG, " Filter is not from package " + packageName + "; skipping"); } continue; } if (!allowFilterResult(filter, dest)) { if (debug) { Slog.v(TAG, " Filter's target already added"); } continue; } match = filter.match(action, resolvedType, scheme, data, categories, TAG); if (match >= 0) { if (debug) Slog.v(TAG, " Filter matched! match=0x" + Integer.toHexString(match)); if (!defaultOnly || filter.hasCategory(Intent.CATEGORY_DEFAULT)) { final R oneResult = newResult(filter, match, userId); if (oneResult != null) { dest.add(oneResult); } } else { hasNonDefaults = true; } } else { if (debug) { String reason; switch (match) { case IntentFilter.NO_MATCH_ACTION: reason = "action"; break; case IntentFilter.NO_MATCH_CATEGORY: reason = "category"; break; case IntentFilter.NO_MATCH_DATA: reason = "data"; break; case IntentFilter.NO_MATCH_TYPE: reason = "type"; break; default: reason = "unknown reason"; break; } Slog.v(TAG, " Filter did not match: " + reason); } } } if (dest.size() == 0 && hasNonDefaults) { Slog.w(TAG, "resolveIntent failed: found match, but none with Intent.CATEGORY_DEFAULT"); } }
|
这个 buildResolveList 中就是循环从输入的 F 数组中取出 F,然后传给一个叫 newResult 的函数构造 R。这个 newResult 是由不同的 IntentResovler 之类实现的。我们来看看 PMS 中的 ActivityIntentResolver newResult 的实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| @Override protected ResolveInfo newResult(PackageParser.ActivityIntentInfo info, int match, int userId) { if (!sUserManager.exists(userId)) return null; if (!mSettings.isEnabledLPr(info.activity.info, mFlags, userId)) { return null; } final PackageParser.Activity activity = info.activity; if (mSafeMode && (activity.info.applicationInfo.flags &ApplicationInfo.FLAG_SYSTEM) == 0) { return null; } PackageSetting ps = (PackageSetting) activity.owner.mExtras; if (ps == null) { return null; } ActivityInfo ai = PackageParser.generateActivityInfo(activity, mFlags, ps.readUserState(userId), userId); if (ai == null) { return null; } final ResolveInfo res = new ResolveInfo(); res.activityInfo = ai; if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) { res.filter = info; } res.priority = info.getPriority(); res.preferredOrder = activity.owner.mPreferredOrder; res.match = match; res.isDefault = info.hasDefault; res.labelRes = info.labelRes; res.nonLocalizedLabel = info.nonLocalizedLabel; res.icon = info.icon; res.system = isSystemApp(res.activityInfo.applicationInfo); return res; }
|
上面就是 new 了一个 ResolverInfo(R),然后用 F(PackageParser.ActivityIntentInfo) 中相应的字段填充自己的字段而已。后面 AMS 从自己那里收集动态注册的接收器,也是差不多的。所以说注册的时候保存的数据,差不多可以说就是接收器数据。
构造完 R 之后,queryIntent 最后对匹配的 R 进行了一下排序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| @SuppressWarnings("unchecked") protected void sortResults(List<R> results) { Collections.sort(results, mResolvePrioritySorter); } @SuppressWarnings("rawtypes") private static final Comparator mResolvePrioritySorter = new Comparator() { public int compare(Object o1, Object o2) { final int q1 = ((IntentFilter) o1).getPriority(); final int q2 = ((IntentFilter) o2).getPriority(); return (q1 > q2) ? -1 : ((q1 < q2) ? 1 : 0); } };
|
这个优先级在注册篇说过了,在 manifest 里面声明 receiver 的 filter 那里设置的(只有系统应用有权限设置)。
a.b 收集动态注册接收器
上面看过收集静态的过程,下面我们来看看收集动态注册的接收器:
1 2 3
| registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false, userId);
|
这个其实和上面静态流程是一样的,只不过 IntentResolver 的实现子类是 AMS 的匿名的一个类而已,我们就直接看看关键的 newResult 就行了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| @Override protected BroadcastFilter newResult(BroadcastFilter filter, int match, int userId) { if (userId == UserHandle.USER_ALL || filter.owningUserId == UserHandle.USER_ALL || userId == filter.owningUserId) { return super.newResult(filter, match, userId); } return null; } @SuppressWarnings("unchecked") protected R newResult(F filter, int match, int userId) { return (R)filter; }
|
AMS 里面的除去前面那个判断,就是直接 new 了一个 R,也难怪,AMS 里面的 F 和 R 都是 BroadcastFilter。到这里 AMS 的 broadcastIntentLocked 就收集到了2个 List:
List receivers = null;
List registeredReceivers = null;
分别是静态注册的接收器(ResolveInfo)和动态注册的接收器(BoradcastFilter)。
b. 分发广播给动态注册接收器
收集完广播匹配的接收器(静态和动态),就要开始分发了。我们接着往下看:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| private final int broadcastIntentLocked(ProcessRecord callerApp, String callerPackage, Intent intent, String resolvedType, IIntentReceiver resultTo, int resultCode, String resultData, Bundle map, String requiredPermission, boolean ordered, boolean sticky, int callingPid, int callingUid, int userId) { ... ... int NR = registeredReceivers != null ? registeredReceivers.size() : 0; if (!ordered && NR > 0) { final BroadcastQueue queue = broadcastQueueForIntent(intent); BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp, callerPackage, callingPid, callingUid, requiredPermission, registeredReceivers, resultTo, resultCode, resultData, map, ordered, sticky, false, userId); if (DEBUG_BROADCAST) Slog.v( TAG, "Enqueueing parallel broadcast " + r); final boolean replaced = replacePending && queue.replaceParallelBroadcastLocked(r); if (!replaced) { queue.enqueueParallelBroadcastLocked(r); queue.scheduleBroadcastsLocked(); } registeredReceivers = null; NR = 0; } ... .... return ActivityManager.BROADCAST_SUCCESS; }
|
这里出现了2个新的数据结构:BroadcastQueue 和 BroadcastRecord。我们来一个一个看,首先是 BroadcastQueue:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| public class BroadcastQueue { static final String TAG = "BroadcastQueue"; static final String TAG_MU = ActivityManagerService.TAG_MU; static final boolean DEBUG_BROADCAST = ActivityManagerService.DEBUG_BROADCAST; static final boolean DEBUG_BROADCAST_LIGHT = ActivityManagerService.DEBUG_BROADCAST_LIGHT; static final boolean DEBUG_MU = ActivityManagerService.DEBUG_MU; static final int MAX_BROADCAST_HISTORY = 25; static final int MAX_BROADCAST_SUMMARY_HISTORY = 100; final ActivityManagerService mService; /** * Recognizable moniker for this queue */ final String mQueueName; /** * Timeout period for this queue's broadcasts */ final long mTimeoutPeriod; /** * Lists of all active broadcasts that are to be executed immediately * (without waiting for another broadcast to finish). Currently this only * contains broadcasts to registered receivers, to avoid spinning up * a bunch of processes to execute IntentReceiver components. Background- * and foreground-priority broadcasts are queued separately. */ final ArrayList<BroadcastRecord> mParallelBroadcasts = new ArrayList<BroadcastRecord>(); /** * List of all active broadcasts that are to be executed one at a time. * The object at the top of the list is the currently activity broadcasts; * those after it are waiting for the top to finish. As with parallel * broadcasts, separate background- and foreground-priority queues are * maintained. */ final ArrayList<BroadcastRecord> mOrderedBroadcasts = new ArrayList<BroadcastRecord>(); ... ... }
|
看注释,说 AMS 中有2个这种 BroacastQueue,一个是前台的,一个是后台的,前台的处理优先级比后台的高一些。然后里面有2个比较重要的 ArrayList:mParallelBroadcasts 和 mOrderedBroadcasts。看名字就很明显了,一个是串行广播记录的,一个是并行广播记录的。然后我们再来看下 BroadcastRecord 的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| class BroadcastRecord extends Binder { final Intent intent; final ProcessRecord callerApp; final String callerPackage; final int callingPid; final int callingUid; final boolean ordered; final boolean sticky; final boolean initialSticky; final int userId; final String requiredPermission; final List receivers; IIntentReceiver resultTo; long dispatchTime; long dispatchClockTime; long receiverTime; long finishTime; int resultCode; String resultData; Bundle resultExtras; boolean resultAbort; int nextReceiver; IBinder receiver; int state; int anrCount; BroadcastQueue queue; ... ... }
|
这个类很简单,除了构造函数给上面一堆字段赋值以外,就没别的的啥操作了。然后上面注意那个 List 记录了 AMS 收集到的广播接收器的信息。接下来我们回到 broadcastIntentLocked 中看看 broadcastQueueForIntent 是怎么决定用哪个广播队列的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| private ActivityManagerService() { Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass()); mFgBroadcastQueue = new BroadcastQueue(this, "foreground", BROADCAST_FG_TIMEOUT); mBgBroadcastQueue = new BroadcastQueue(this, "background", BROADCAST_BG_TIMEOUT); mBroadcastQueues[0] = mFgBroadcastQueue; mBroadcastQueues[1] = mBgBroadcastQueue; ... ... } BroadcastQueue broadcastQueueForIntent(Intent intent) { final boolean isFg = (intent.getFlags() & Intent.FLAG_RECEIVER_FOREGROUND) != 0; if (DEBUG_BACKGROUND_BROADCAST) { Slog.i(TAG, "Broadcast intent " + intent + " on " + (isFg ? "foreground" : "background") + " queue"); } return (isFg) ? mFgBroadcastQueue : mBgBroadcastQueue; }
|
看样子是根据发广播的时候的 Intent 的 flags 来决定的,默认不设置就是后台广播队列。我搜了下代码,发现就只有 AMS 中会发几个是前台的。我们确定了我们的列子 BOOT_COMPLETED 是用后台广播队列之后,就来看看 BroadcastQueue 中的加入队列和执行操作:
1 2 3 4
| public void enqueueParallelBroadcastLocked(BroadcastRecord r) { mParallelBroadcasts.add(r); }
|
入队操作很简单,直接插入到并行广播记录的列表中。排好队之后就到执行广播了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| public void scheduleBroadcastsLocked() { RuntimeException here = new RuntimeException("here"); here.fillInStackTrace(); Slog.d(TAG, "call statck is", here); if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts [" + mQueueName + "]: current=" + mBroadcastsScheduled); if (mBroadcastsScheduled) { return; } mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this)); mBroadcastsScheduled = true; } final Handler mHandler = new Handler() { public void handleMessage(Message msg) { switch (msg.what) { case BROADCAST_INTENT_MSG: { if (DEBUG_BROADCAST) Slog.v( TAG, "Received BROADCAST_INTENT_MSG"); processNextBroadcast(true); } break; case BROADCAST_TIMEOUT_MSG: { synchronized (mService) { broadcastTimeoutLocked(true); } } break; } } };
|
最后执行操作是由 processNextBroadcast 这个函数来完成的。这个函数非常的长(将近 500 行),我们得分功能一段一段来:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| final void processNextBroadcast(boolean fromMsg) { synchronized(mService) { BroadcastRecord r; if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast [" + mQueueName + "]: " + mParallelBroadcasts.size() + " broadcasts, " + mOrderedBroadcasts.size() + " ordered broadcasts"); mService.updateCpuStats(); if (fromMsg) { mBroadcastsScheduled = false; } while (mParallelBroadcasts.size() > 0) { r = mParallelBroadcasts.remove(0); r.dispatchTime = SystemClock.uptimeMillis(); r.dispatchClockTime = System.currentTimeMillis(); final int N = r.receivers.size(); if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast [" + mQueueName + "] " + r); for (int i=0; i<N; i++) { Object target = r.receivers.get(i); if (DEBUG_BROADCAST) Slog.v(TAG, "Delivering non-ordered on [" + mQueueName + "] to registered " + target + ": " + r); deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false); } addBroadcastToHistoryLocked(r); if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast [" + mQueueName + "] " + r); } ... ... }
|
我们接下去看 deliverToRegisteredReceiverLocked:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
| private final void deliverToRegisteredReceiverLocked(BroadcastRecord r, BroadcastFilter filter, boolean ordered) { boolean skip = false; if (filter.requiredPermission != null) { int perm = mService.checkComponentPermission(filter.requiredPermission, r.callingPid, r.callingUid, -1, true); if (perm != PackageManager.PERMISSION_GRANTED) { Slog.w(TAG, "Permission Denial: broadcasting " + r.intent.toString() + " from " + r.callerPackage + " (pid=" + r.callingPid + ", uid=" + r.callingUid + ")" + " requires " + filter.requiredPermission + " due to registered receiver " + filter); skip = true; } } if (!skip && r.requiredPermission != null) { int perm = mService.checkComponentPermission(r.requiredPermission, filter.receiverList.pid, filter.receiverList.uid, -1, true); if (perm != PackageManager.PERMISSION_GRANTED) { Slog.w(TAG, "Permission Denial: receiving " + r.intent.toString() + " to " + filter.receiverList.app + " (pid=" + filter.receiverList.pid + ", uid=" + filter.receiverList.uid + ")" + " requires " + r.requiredPermission + " due to sender " + r.callerPackage + " (uid " + r.callingUid + ")"); skip = true; } } if (!skip) { if (ordered) { r.receiver = filter.receiverList.receiver.asBinder(); r.curFilter = filter; filter.receiverList.curBroadcast = r; r.state = BroadcastRecord.CALL_IN_RECEIVE; if (filter.receiverList.app != null) { r.curApp = filter.receiverList.app; filter.receiverList.app.curReceiver = r; mService.updateOomAdjLocked(); } } try { if (DEBUG_BROADCAST_LIGHT) { int seq = r.intent.getIntExtra("seq", -1); Slog.i(TAG, "Delivering to " + filter + " (seq=" + seq + "): " + r); } performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver, new Intent(r.intent), r.resultCode, r.resultData, r.resultExtras, r.ordered, r.initialSticky, r.userId); if (ordered) { r.state = BroadcastRecord.CALL_DONE_RECEIVE; } } catch (RemoteException e) { Slog.w(TAG, "Failure sending broadcast " + r.intent, e); if (ordered) { r.receiver = null; r.curFilter = null; filter.receiverList.curBroadcast = null; if (filter.receiverList.app != null) { filter.receiverList.app.curReceiver = null; } } } } }
|
这个分发函数把前面的权限检测和那个串行处理忽略掉之后,就剩下 performReceiveLocked 这个处理了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| private static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver, Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser) throws RemoteException { if (app != null && app.thread != null) { app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode, data, extras, ordered, sticky, sendingUser); } else { receiver.performReceive(intent, resultCode, data, extras, ordered, sticky, sendingUser); } }
|
这里首先,我们复习下传过来的参数: ProcessRecord 是动态注册的时候构造 ReceiverList 保存的接收器注册者的进程记录信息;IIntentReceiver 这个东西也是在动态注册的时候构造 BroadcastFilter 保存的接收器注册者的 LoadedApk.ReceiverDispatcher.InnerReceiver 这个对象的 Bp 端(这个的 Bn 端就有接收器最终的 onReceiver 回调,忘记了去注册篇复习下)。这里虽然分了2种情况:
- 接收器进程还在运行(app != null && app.thread != null)
- 接收器进程已经挂了
我个人认为正常情况,只有会第一种,第二种是不会有的,就算有这次的广播也无法正常发送。为什么呢,下面来解释一下(这里我没做验证,是光看代码的,但是感觉应该没错):
第一,如果发生了第二种情况,IIntentReceiver 这个接口的实现是用 aidl 弄的,自己去 out 下翻一下,会发现这个接口没有判断 Bn 不在的情况下,启动进程的情况,也就是说如果接收器进程挂了,调用这个 IPC 接口,根本不会重新启动接收器进程。那就是说这种情况下 IPC 通信是会失败的,因为 Bn 没了。
第二,其实正常情况下,上面那种情况不会出现。去注册篇仔细看下 AMS 的 registerReceiver 注册了一个 IIntentReceiver 的死亡通知回调:
receiver.asBinder().linkToDeath(rl, 0);
当动态动态的接收器进程挂了,会调用这个一个东西:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| class ReceiverList extends ArrayList<BroadcastFilter> implements IBinder.DeathRecipient { final ActivityManagerService owner; public final IIntentReceiver receiver; ... ... public void binderDied() { linkedToDeath = false; owner.unregisterReceiver(receiver); } ... .... }
|
就相当于如果动态注册的接收器进程挂了,AMS 会自动注销它的,我们稍微看下 AMS 的 unregisterReceiver:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
| public void unregisterReceiver(IIntentReceiver receiver) { if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver); final long origId = Binder.clearCallingIdentity(); try { boolean doTrim = false; synchronized(this) { ReceiverList rl = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder()); if (rl != null) { if (rl.curBroadcast != null) { BroadcastRecord r = rl.curBroadcast; final boolean doNext = finishReceiverLocked( receiver.asBinder(), r.resultCode, r.resultData, r.resultExtras, r.resultAbort, true); if (doNext) { doTrim = true; r.queue.processNextBroadcast(false); } } if (rl.app != null) { rl.app.receivers.remove(rl); } removeReceiverLocked(rl); if (rl.linkedToDeath) { rl.linkedToDeath = false; rl.receiver.asBinder().unlinkToDeath(rl, 0); } } } if (doTrim) { trimApplications(); return; } } finally { Binder.restoreCallingIdentity(origId); } } void removeReceiverLocked(ReceiverList rl) { mRegisteredReceivers.remove(rl.receiver.asBinder()); int N = rl.size(); for (int i=0; i<N; i++) { mReceiverResolver.removeFilter(rl.get(i)); } }
|
所以说正常情况下,动态注册的接收器进程挂了,broadcastIntentLocked 的时候根本就查询不到有这个接收器的。所以第二种情况基本上不会发生吧。这里我们直接看第一种情况,就是接收器进程正在运行(这才是正常情况,要不然怎么叫动态注册咧)。这个时候就可以直接调用 IApplicationThread 的 scheduleRegisteredReceiver 函数执行接收器函数。看这个名字就知道 IPC 调用了,这个是当然的,接收器在另外的进程里面(广播处理的是在 AMS 中,system_server 进程)。然后我们去 Bn 端看看(这个时候我们是在接收器的进程了,):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| private class ApplicationThread extends ApplicationThreadNative { ... ... public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent, int resultCode, String dataStr, Bundle extras, boolean ordered, boolean sticky, int sendingUser) throws RemoteException { receiver.performReceive(intent, resultCode, dataStr, extras, ordered, sticky, sendingUser); } ... ... }
|
IIntentReceiver 再经过 IPC 传到接收器进程,已经是 Bn 端了,我们终于可以去看注册篇里面那个 LoadedApk 的内部类的内部类的 InnerReceiver 了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| final static class InnerReceiver extends IIntentReceiver.Stub { final WeakReference<LoadedApk.ReceiverDispatcher> mDispatcher; final LoadedApk.ReceiverDispatcher mStrongRef; InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) { mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd); mStrongRef = strong ? rd : null; } public void performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser) { LoadedApk.ReceiverDispatcher rd = mDispatcher.get(); if (ActivityThread.DEBUG_BROADCAST) { int seq = intent.getIntExtra("seq", -1); Slog.i(ActivityThread.TAG, "Receiving broadcast " + intent.getAction() + " seq=" + seq + " to " + (rd != null ? rd.mReceiver : null)); } if (rd != null) { rd.performReceive(intent, resultCode, data, extras, ordered, sticky, sendingUser); } else { if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG, "Finishing broadcast to unregistered receiver"); IActivityManager mgr = ActivityManagerNative.getDefault(); try { if (extras != null) { extras.setAllowFds(false); } mgr.finishReceiver(this, resultCode, data, extras, false); } catch (RemoteException e) { Slog.w(ActivityThread.TAG, "Couldn't finish broadcast to unregistered receiver"); } } } }
|
这里继续去看 LoadedApk.ReceiverDispatcher 的 performReceive:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| public void performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser) { if (ActivityThread.DEBUG_BROADCAST) { int seq = intent.getIntExtra("seq", -1); Slog.i(ActivityThread.TAG, "Enqueueing broadcast " + intent.getAction() + " seq=" + seq + " to " + mReceiver); } Args args = new Args(intent, resultCode, data, extras, ordered, sticky, sendingUser); if (!mActivityThread.post(args)) { if (mRegistered && ordered) { IActivityManager mgr = ActivityManagerNative.getDefault(); if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG, "Finishing sync broadcast to " + mReceiver); args.sendFinished(mgr); } } }
|
还记得注册篇中注册的接口时候有一个 Handler 的可选参数的么,那个是可以让调用者指定接收器运行的线程(Handler 所运行的线程,如果没指定的话,默认使用调用者所在进程的主线程)。这个 mActivityThread 就是保存了注册时候的那个 Handler:
final Handler mActivityThread;
叫 mActivityThread 其实是一个 Handler,所以这里其实是把接收器扔到注册的时候指定的线程去执行去了。然后我们接下去看 Args 这个东西:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
| final class Args extends BroadcastReceiver.PendingResult implements Runnable { private Intent mCurIntent; private final boolean mOrdered; public Args(Intent intent, int resultCode, String resultData, Bundle resultExtras, boolean ordered, boolean sticky, int sendingUser) { super(resultCode, resultData, resultExtras, mRegistered ? TYPE_REGISTERED : TYPE_UNREGISTERED, ordered, sticky, mIIntentReceiver.asBinder(), sendingUser); mCurIntent = intent; mOrdered = ordered; } public void run() { final BroadcastReceiver receiver = mReceiver; final boolean ordered = mOrdered; if (ActivityThread.DEBUG_BROADCAST) { int seq = mCurIntent.getIntExtra("seq", -1); Slog.i(ActivityThread.TAG, "Dispatching broadcast " + mCurIntent.getAction() + " seq=" + seq + " to " + mReceiver); Slog.i(ActivityThread.TAG, " mRegistered=" + mRegistered + " mOrderedHint=" + ordered); } final IActivityManager mgr = ActivityManagerNative.getDefault(); final Intent intent = mCurIntent; mCurIntent = null; if (receiver == null || mForgotten) { if (mRegistered && ordered) { if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG, "Finishing null broadcast to " + mReceiver); } return; } Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveReg"); try { ClassLoader cl = mReceiver.getClass().getClassLoader(); intent.setExtrasClassLoader(cl); setExtrasClassLoader(cl); receiver.setPendingResult(this); receiver.onReceive(mContext, intent); } catch (Exception e) { if (mRegistered && ordered) { if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG, "Finishing failed broadcast to " + mReceiver); sendFinished(mgr); } if (mInstrumentation == null || !mInstrumentation.onException(mReceiver, e)) { Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); throw new RuntimeException( "Error receiving broadcast " + intent + " in " + mReceiver, e); } } if (receiver.getPendingResult() != null) { finish(); } Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); } }
|
LoadedApk.ReceiverDispatcher 的 mReceiver 就是注册广播接收器的时候 new LoadedApk.ReceiverDispatcher 传进来那个 BroadcastReceiver 对象(忘记的回去注册篇看看)。这里在执行的线程中跑 run 函数,最终调用到了注册者实现的 BroadcastReceiver 的 onReceive 回调。到这里一个动态注册的广播接收器就算处理完成了。
这里回到前面 performReceive 的 mActivityThread.post 那里。前面说了现在是处理并行广播,怎么体现出来是并行的咧。再回去远一点,从接收器进程回到 AMS 的 processNextBroadcast 的那个 while 循环那里:
1 2 3 4 5 6 7 8 9 10
| final void processNextBroadcast(boolean fromMsg) { synchronized(mService) { while (mParallelBroadcasts.size() > 0) { for (int i=0; i<N; i++) { deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false); } } ... ... }
|
因为 performReceive 那里是 post 了一个 Runnable(LoadedApk.ReceiverDispatcher.Args)到一个 Handler 中,所以会马上返回(不会等待接收器的执行),所以 IPC 也会马上从接收器进程返回到 AMS 这边,所以 while(for)循环就会继续往下执行下一个接收器的处理。从精确的角度说虽然还是会有先后,但是广播这的东西本身不是什么太精准的东西,所以约等于是并行处理了。
这里我们从 processNextBroadcast 分段那里直接返回,因为后面是串行广播的处理(静态注册的接收器),然后我们就可以回到 AMS 的 broadcastIntentLocked 继续往下走了。
c. 分发广播给静态注册接收器
我们接着往下看 broadcastIntentLocked,下面是这么一段:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
| int ir = 0; if (receivers != null) { String skipPackages[] = null; if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction()) || Intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction()) || Intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) { Uri data = intent.getData(); if (data != null) { String pkgName = data.getSchemeSpecificPart(); if (pkgName != null) { skipPackages = new String[] { pkgName }; } } } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) { skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST); } if (skipPackages != null && (skipPackages.length > 0)) { for (String skipPackage : skipPackages) { if (skipPackage != null) { int NT = receivers.size(); for (int it=0; it<NT; it++) { ResolveInfo curt = (ResolveInfo)receivers.get(it); if (curt.activityInfo.packageName.equals(skipPackage)) { receivers.remove(it); it--; NT--; } } } } } int NT = receivers != null ? receivers.size() : 0; int it = 0; ResolveInfo curt = null; BroadcastFilter curr = null; while (it < NT && ir < NR) { if (curt == null) { curt = (ResolveInfo)receivers.get(it); } if (curr == null) { curr = registeredReceivers.get(ir); } if (curr.getPriority() >= curt.priority) { receivers.add(it, curr); ir++; curr = null; it++; NT++; } else { it++; curt = null; } } } while (ir < NR) { if (receivers == null) { receivers = new ArrayList(); } receivers.add(registeredReceivers.get(ir)); ir++; }
|
这段就是将剩下还没处理的动态注册的接收器合并到静态注册接收器的 list 里面去了,然后下面是 broadcastIntentLocked 的最后一段,串行处理静态注册接收器(包括强制发串行广播的动态注册的接收器):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| private final int broadcastIntentLocked(ProcessRecord callerApp, String callerPackage, Intent intent, String resolvedType, IIntentReceiver resultTo, int resultCode, String resultData, Bundle map, String requiredPermission, boolean ordered, boolean sticky, int callingPid, int callingUid, int userId) { ... ... if ((receivers != null && receivers.size() > 0) || resultTo != null) { BroadcastQueue queue = broadcastQueueForIntent(intent); BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp, callerPackage, callingPid, callingUid, requiredPermission, receivers, resultTo, resultCode, resultData, map, ordered, sticky, false, userId); if (DEBUG_BROADCAST) Slog.v( TAG, "Enqueueing ordered broadcast " + r + ": prev had " + queue.mOrderedBroadcasts.size()); if (DEBUG_BROADCAST) { int seq = r.intent.getIntExtra("seq", -1); Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq); } boolean replaced = replacePending && queue.replaceOrderedBroadcastLocked(r); if (!replaced) { queue.enqueueOrderedBroadcastLocked(r); queue.scheduleBroadcastsLocked(); } } return ActivityManager.BROADCAST_SUCCESS; }
|
这里唯一和前面的区别就是处理的接收器的列表不一样,然后在 BroadcastQueue 中排队的队列也不一样。我们可以直接跳到前面的 processNextBroadcast 返回那里(前面那些流程都是一样的):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| if (mPendingBroadcast != null) { if (DEBUG_BROADCAST_LIGHT) { Slog.v(TAG, "processNextBroadcast [" + mQueueName + "]: waiting for " + mPendingBroadcast.curApp); } boolean isDead; synchronized (mService.mPidsSelfLocked) { isDead = (mService.mPidsSelfLocked.get( mPendingBroadcast.curApp.pid) == null); } if (!isDead) { return; } else { Slog.w(TAG, "pending app [" + mQueueName + "]" + mPendingBroadcast.curApp + " died before responding to broadcast"); mPendingBroadcast.state = BroadcastRecord.IDLE; mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex; mPendingBroadcast = null; } } boolean looped = false; do { if (mOrderedBroadcasts.size() == 0) { mService.scheduleAppGcsLocked(); if (looped) { mService.updateOomAdjLocked(); } return; } r = mOrderedBroadcasts.get(0); boolean forceReceive = false; ... ... } while (r == null);
|
上面的简单过过就行,一些东西我们这里不去深究,继续看下面:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| int recIdx = r.nextReceiver++; r.receiverTime = SystemClock.uptimeMillis(); if (recIdx == 0) { r.dispatchTime = r.receiverTime; r.dispatchClockTime = System.currentTimeMillis(); if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast [" + mQueueName + "] " + r); } if (! mPendingBroadcastTimeoutMessage) { long timeoutTime = r.receiverTime + mTimeoutPeriod; if (DEBUG_BROADCAST) Slog.v(TAG, "Submitting BROADCAST_TIMEOUT_MSG [" + mQueueName + "] for " + r + " at " + timeoutTime); setBroadcastTimeoutLocked(timeoutTime); } Object nextReceiver = r.receivers.get(recIdx); if (nextReceiver instanceof BroadcastFilter) { BroadcastFilter filter = (BroadcastFilter)nextReceiver; if (DEBUG_BROADCAST) Slog.v(TAG, "Delivering ordered [" + mQueueName + "] to registered " + filter + ": " + r); deliverToRegisteredReceiverLocked(r, filter, r.ordered); if (r.receiver == null || !r.ordered) { if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing [" + mQueueName + "]: ordered=" + r.ordered + " receiver=" + r.receiver); r.state = BroadcastRecord.IDLE; scheduleBroadcastsLocked(); } return; }
|
到这里其实都还不是静态注册接收器的处理,只是把前面动态注册的接收器串行处理了而已,流程前面说过了。现在我们继续往下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
| ResolveInfo info = (ResolveInfo)nextReceiver; ComponentName component = new ComponentName( info.activityInfo.applicationInfo.packageName, info.activityInfo.name); boolean skip = false; int perm = mService.checkComponentPermission(info.activityInfo.permission, r.callingPid, r.callingUid, info.activityInfo.applicationInfo.uid, info.activityInfo.exported); if (perm != PackageManager.PERMISSION_GRANTED) { if (!info.activityInfo.exported) { Slog.w(TAG, "Permission Denial: broadcasting " + r.intent.toString() + " from " + r.callerPackage + " (pid=" + r.callingPid + ", uid=" + r.callingUid + ")" + " is not exported from uid " + info.activityInfo.applicationInfo.uid + " due to receiver " + component.flattenToShortString()); } else { Slog.w(TAG, "Permission Denial: broadcasting " + r.intent.toString() + " from " + r.callerPackage + " (pid=" + r.callingPid + ", uid=" + r.callingUid + ")" + " requires " + info.activityInfo.permission + " due to receiver " + component.flattenToShortString()); } skip = true; } if (info.activityInfo.applicationInfo.uid != Process.SYSTEM_UID && r.requiredPermission != null) { try { perm = AppGlobals.getPackageManager(). checkPermission(r.requiredPermission, info.activityInfo.applicationInfo.packageName); } catch (RemoteException e) { perm = PackageManager.PERMISSION_DENIED; } if (perm != PackageManager.PERMISSION_GRANTED) { Slog.w(TAG, "Permission Denial: receiving " + r.intent + " to " + component.flattenToShortString() + " requires " + r.requiredPermission + " due to sender " + r.callerPackage + " (uid " + r.callingUid + ")"); skip = true; } } boolean isSingleton = false; try { isSingleton = mService.isSingleton(info.activityInfo.processName, info.activityInfo.applicationInfo, info.activityInfo.name, info.activityInfo.flags); } catch (SecurityException e) { Slog.w(TAG, e.getMessage()); skip = true; } if ((info.activityInfo.flags&ActivityInfo.FLAG_SINGLE_USER) != 0) { if (ActivityManager.checkUidPermission( android.Manifest.permission.INTERACT_ACROSS_USERS, info.activityInfo.applicationInfo.uid) != PackageManager.PERMISSION_GRANTED) { Slog.w(TAG, "Permission Denial: Receiver " + component.flattenToShortString() + " requests FLAG_SINGLE_USER, but app does not hold " + android.Manifest.permission.INTERACT_ACROSS_USERS); skip = true; } } if (r.curApp != null && r.curApp.crashing) { if (DEBUG_BROADCAST) Slog.v(TAG, "Skipping deliver ordered [" + mQueueName + "] " + r + " to " + r.curApp + ": process crashing"); skip = true; } if (skip) { if (DEBUG_BROADCAST) Slog.v(TAG, "Skipping delivery of ordered [" + mQueueName + "] " + r + " for whatever reason"); r.receiver = null; r.curFilter = null; r.state = BroadcastRecord.IDLE; scheduleBroadcastsLocked(); return; }
|
上面这一段我们也可以简单略过,就是权限检测,检测当前这个接收器有没有权限处理这次的广播,如果没有就忽略这个接收器;还有判断了接收器所在的进程是不是挂掉了,挂掉了也忽略这个接收器。我们接下来继续:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| r.state = BroadcastRecord.APP_RECEIVE; String targetProcess = info.activityInfo.processName; r.curComponent = component; if (r.callingUid != Process.SYSTEM_UID && isSingleton) { info.activityInfo = mService.getActivityInfoForUser(info.activityInfo, 0); } r.curReceiver = info.activityInfo; if (DEBUG_MU && r.callingUid > UserHandle.PER_USER_RANGE) { Slog.v(TAG_MU, "Updated broadcast record activity info for secondary user, " + info.activityInfo + ", callingUid = " + r.callingUid + ", uid = " + info.activityInfo.applicationInfo.uid); } try { AppGlobals.getPackageManager().setPackageStoppedState( r.curComponent.getPackageName(), false, UserHandle.getUserId(r.callingUid)); } catch (RemoteException e) { } catch (IllegalArgumentException e) { Slog.w(TAG, "Failed trying to unstop package " + r.curComponent.getPackageName() + ": " + e); }
|
下面就要分2种情况来讨论。还记得 Android Binder 分析——普通服务 Binder 对象的传递 中分了3种情况来讨论启动普通应用的服务,这里也是同样的道理。要分为接收器的进程是否已经启动在讨论:
接收器进程已经启动
我们先来看简单的情况,接收器的进程已经启动。这种情况不需要等待接收器进程启动,可以直接发起 IPC 调用,在接收器进程中跑处理广播的回调:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| ProcessRecord app = mService.getProcessRecordLocked(targetProcess, info.activityInfo.applicationInfo.uid); if (app != null && app.thread != null) { try { app.addPackage(info.activityInfo.packageName); processCurBroadcastLocked(r, app); return; } catch (RemoteException e) { Slog.w(TAG, "Exception when sending broadcast to " + r.curComponent, e); } catch (RuntimeException e) { Log.wtf(TAG, "Failed sending broadcast to " + r.curComponent + " with " + r.intent, e); logBroadcastReceiverDiscardLocked(r); finishReceiverLocked(r, r.resultCode, r.resultData, r.resultExtras, r.resultAbort, true); scheduleBroadcastsLocked(); r.state = BroadcastRecord.IDLE; return; } }
|
我们接着去看 processCurBroadcastLocked:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| private final void processCurBroadcastLocked(BroadcastRecord r, ProcessRecord app) throws RemoteException { if (DEBUG_BROADCAST) Slog.v(TAG, "Process cur broadcast " + r + " for app " + app); if (app.thread == null) { throw new RemoteException(); } r.receiver = app.thread.asBinder(); r.curApp = app; app.curReceiver = r; mService.updateLruProcessLocked(app, true); r.intent.setComponent(r.curComponent); boolean started = false; try { if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Delivering to component " + r.curComponent + ": " + r); mService.ensurePackageDexOpt(r.intent.getComponent().getPackageName()); app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver, mService.compatibilityInfoForPackageLocked(r.curReceiver.applicationInfo), r.resultCode, r.resultData, r.resultExtras, r.ordered, r.userId); if (DEBUG_BROADCAST) Slog.v(TAG, "Process cur broadcast " + r + " DELIVERED for app " + app); started = true; } finally { if (!started) { if (DEBUG_BROADCAST) Slog.v(TAG, "Process cur broadcast " + r + ": NOT STARTED!"); r.receiver = null; r.curApp = null; app.curReceiver = null; } } }
|
和前面动态注册的一样,经过 IPC 调用,我们得跑到接收器的进程中去了,还是 ActivityThread.java:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| public final class ActivityThread { ... ... private class ApplicationThread extends ApplicationThreadNative { ... ... public final void scheduleReceiver(Intent intent, ActivityInfo info, CompatibilityInfo compatInfo, int resultCode, String data, Bundle extras, boolean sync, int sendingUser) { ReceiverData r = new ReceiverData(intent, resultCode, data, extras, sync, false, mAppThread.asBinder(), sendingUser); r.info = info; r.compatInfo = compatInfo; queueOrSendMessage(H.RECEIVER, r); } ... ... } ... ... }
|
这里其实就是用了一个 Handler 又绕了半天,最终的处理函数是 handleReceiver:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
| public final class ActivityThread { ... ... final H mH = new H(); ... ... private void queueOrSendMessage(int what, Object obj) { queueOrSendMessage(what, obj, 0, 0); } private void queueOrSendMessage(int what, Object obj, int arg1, int arg2) { synchronized (this) { if (DEBUG_MESSAGES) Slog.v( TAG, "SCHEDULE " + what + " " + mH.codeToString(what) + ": " + arg1 + " / " + obj); Message msg = Message.obtain(); msg.what = what; msg.obj = obj; msg.arg1 = arg1; msg.arg2 = arg2; mH.sendMessage(msg); } } ... ... private class H extends Handler { ... ... public static final int RECEIVER = 113; public static final int CREATE_SERVICE = 114; ... ... public void handleMessage(Message msg) { if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what)); switch (msg.what) { ... ... case RECEIVER: Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveComp"); handleReceiver((ReceiverData)msg.obj); maybeSnapshot(); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); break; ... ... } if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + codeToString(msg.what)); } ... ... } ... ... private void handleReceiver(ReceiverData data) { unscheduleGcIdler(); String component = data.intent.getComponent().getClassName(); LoadedApk packageInfo = getPackageInfoNoCheck( data.info.applicationInfo, data.compatInfo); IActivityManager mgr = ActivityManagerNative.getDefault(); BroadcastReceiver receiver; try { java.lang.ClassLoader cl = packageInfo.getClassLoader(); data.intent.setExtrasClassLoader(cl); data.setExtrasClassLoader(cl); receiver = (BroadcastReceiver)cl.loadClass(component).newInstance(); } catch (Exception e) { if (DEBUG_BROADCAST) Slog.i(TAG, "Finishing failed broadcast to " + data.intent.getComponent()); data.sendFinished(mgr); throw new RuntimeException( "Unable to instantiate receiver " + component + ": " + e.toString(), e); } try { Application app = packageInfo.makeApplication(false, mInstrumentation); if (localLOGV) Slog.v( TAG, "Performing receive of " + data.intent + ": app=" + app + ", appName=" + app.getPackageName() + ", pkg=" + packageInfo.getPackageName() + ", comp=" + data.intent.getComponent().toShortString() + ", dir=" + packageInfo.getAppDir()); ContextImpl context = (ContextImpl)app.getBaseContext(); sCurrentBroadcastIntent.set(data.intent); receiver.setPendingResult(data); receiver.onReceive(context.getReceiverRestrictedContext(), data.intent); } catch (Exception e) { if (DEBUG_BROADCAST) Slog.i(TAG, "Finishing failed broadcast to " + data.intent.getComponent()); data.sendFinished(mgr); if (!mInstrumentation.onException(receiver, e)) { throw new RuntimeException( "Unable to start receiver " + component + ": " + e.toString(), e); } } finally { sCurrentBroadcastIntent.set(null); } if (receiver.getPendingResult() != null) { data.finish(); } } ... ... }
|
上面的处理最终调到 onReceiver 了。但是想想看,还是有一个地方没搞明白。前面说了静态注册的接收器是串行执行广播处理的,就是等到当前的那个执行完,才能执行下一个。好了,现在我们来解释下这个串行执行是怎么实现的。回到 AMS 那边的 processNextBroadcast 调用 processCurBroadcastLocked 那里:
1 2 3 4 5 6
| try { app.addPackage(info.activityInfo.packageName); processCurBroadcastLocked(r, app); return; } catch
|
这里就是刚刚我们上面分析的流程,IPC 调用到接收器进程的 onReceive 回调。然后这里 processNextBroadcast 就返回了。AMS 执行 BroadcastQueue.scheduleBroadcastsLocked() 早就返回了,因为 BroadcastQueue 里面是发到 Handler 里面处理 processNextBroadcast 的,然后 processNextBroadcast 结束后, AMS 好像这次广播处理就结束了。可是这才执行了第一个静态注册的接收器而已啊。这个时候去看接收器 handleReceiver 最后有一个:
data.finish()
这个 finish 是要等到 onReceive 执行完才会调用的(也就是说这个接收器处理完了)。前面说了这个 finish 很关键的,我们来看看 finish 里面做了什么事情。在这里之前得先看看 ReceiverData 这个对象:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| static final class ReceiverData extends BroadcastReceiver.PendingResult { public ReceiverData(Intent intent, int resultCode, String resultData, Bundle resultExtras, boolean ordered, boolean sticky, IBinder token, int sendingUser) { super(resultCode, resultData, resultExtras, TYPE_COMPONENT, ordered, sticky, token, sendingUser); this.intent = intent; } Intent intent; ActivityInfo info; CompatibilityInfo compatInfo; public String toString() { return "ReceiverData{intent=" + intent + " packageName=" + info.packageName + " resultCode=" + getResultCode() + " resultData=" + getResultData() + " resultExtras=" + getResultExtras(false) + "}"; } }
|
这个 ReceiverData 是前面 scheduleReceiver 那里 new 出来的,它是继承自 BroadcastReceiver.PendingResult,这得去父类里面去看看:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| public final void finish() { if (mType == TYPE_COMPONENT) { final IActivityManager mgr = ActivityManagerNative.getDefault(); if (QueuedWork.hasPendingWork()) { QueuedWork.singleThreadExecutor().execute( new Runnable() { @Override public void run() { if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG, "Finishing broadcast after work to component " + mToken); Slog.i(ActivityThread.TAG, "Finishing broadcast after work to component " + mToken); sendFinished(mgr); } }); } else { if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG, "Finishing broadcast to component " + mToken); Slog.i(ActivityThread.TAG, "Finishing broadcast to component " + mToken); sendFinished(mgr); } } else if (mOrderedHint && mType != TYPE_UNREGISTERED) { if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG, "Finishing broadcast to " + mToken); Slog.i(ActivityThread.TAG, "Finishing broadcast to " + mToken); final IActivityManager mgr = ActivityManagerNative.getDefault(); sendFinished(mgr); } }
|
继续去看 sendFinished:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| public void sendFinished(IActivityManager am) { synchronized (this) { if (mFinished) { throw new IllegalStateException("Broadcast already finished"); } mFinished = true; try { if (mResultExtras != null) { mResultExtras.setAllowFds(false); } if (mOrderedHint) { am.finishReceiver(mToken, mResultCode, mResultData, mResultExtras, mAbortBroadcast); } else { am.finishReceiver(mToken, 0, null, null, false); } } catch (RemoteException ex) { } } }
|
好,这里接收器进程处理完广播之后,finish 最后有调回 AMS 里面,看到这里是不是猜到了什么呢。对的,没错,串行广播一个接一个的执行是靠前一个接收器执行完,通知 AMS 把广播发给下一个接收器接着处理来实现的。虽然猜到了,但是我们还是继续去 AMS 里面看完流程:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| public void finishReceiver(IBinder who, int resultCode, String resultData, Bundle resultExtras, boolean resultAbort) { if (DEBUG_BROADCAST) Slog.v(TAG, "Finish receiver: " + who); if (resultExtras != null && resultExtras.hasFileDescriptors()) { throw new IllegalArgumentException("File descriptors passed in Bundle"); } final long origId = Binder.clearCallingIdentity(); try { boolean doNext = false; BroadcastRecord r = null; synchronized(this) { r = broadcastRecordForReceiverLocked(who); if (r != null) { doNext = r.queue.finishReceiverLocked(r, resultCode, resultData, resultExtras, resultAbort, true); } } if (doNext) { r.queue.processNextBroadcast(false); } trimApplications(); } finally { Binder.restoreCallingIdentity(origId); } }
|
我们先来看看怎么取上次处理完成的 BroadcastRecord 的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| BroadcastRecord broadcastRecordForReceiverLocked(IBinder receiver) { for (BroadcastQueue queue : mBroadcastQueues) { BroadcastRecord r = queue.getMatchingOrderedReceiver(receiver); if (r != null) { return r; } } return null; } public BroadcastRecord getMatchingOrderedReceiver(IBinder receiver) { if (mOrderedBroadcasts.size() > 0) { final BroadcastRecord r = mOrderedBroadcasts.get(0); if (r != null && r.receiver == receiver) { return r; } } return null; }
|
这里取到了上一个接收器的 BroadcastRecord,接着去 BroadcastQueue 中看看 finishReceiverLocked:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| public boolean finishReceiverLocked(BroadcastRecord r, int resultCode, String resultData, Bundle resultExtras, boolean resultAbort, boolean explicit) { int state = r.state; r.state = BroadcastRecord.IDLE; if (state == BroadcastRecord.IDLE) { if (explicit) { Slog.w(TAG, "finishReceiver [" + mQueueName + "] called but state is IDLE"); } } r.receiver = null; r.intent.setComponent(null); if (r.curApp != null) { r.curApp.curReceiver = null; } if (r.curFilter != null) { r.curFilter.receiverList.curBroadcast = null; } r.curFilter = null; r.curApp = null; r.curComponent = null; r.curReceiver = null; mPendingBroadcast = null; r.resultCode = resultCode; r.resultData = resultData; r.resultExtras = resultExtras; r.resultAbort = resultAbort; return state == BroadcastRecord.APP_RECEIVE || state == BroadcastRecord.CALL_DONE_RECEIVE; }
|
这个 BroadcastRecord 的 state,待会我们再讨论。这里正常 finishReceiverLocked 返回 true,就意味着 AMS 会继续调用 BroadcastQueue 的 processNextBroadcast 继续处理。这个 processNextBroadcast 我们前面分析了好久了,不过这里和前面不太一样,首先传过去的参数为 false:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
| final void processNextBroadcast(boolean fromMsg) { synchronized(mService) { BroadcastRecord r; ... ... if (fromMsg) { mBroadcastsScheduled = false; } ... ... ... ... do { if (mOrderedBroadcasts.size() == 0) { mService.scheduleAppGcsLocked(); if (looped) { mService.updateOomAdjLocked(); } return; } r = mOrderedBroadcasts.get(0); boolean forceReceive = false; int numReceivers = (r.receivers != null) ? r.receivers.size() : 0; if (mService.mProcessesReady && r.dispatchTime > 0) { long now = SystemClock.uptimeMillis(); if ((numReceivers > 0) && (now > r.dispatchTime + (2*mTimeoutPeriod*numReceivers))) { Slog.w(TAG, "Hung broadcast [" + mQueueName + "] discarded after timeout failure:" + " now=" + now + " dispatchTime=" + r.dispatchTime + " startTime=" + r.receiverTime + " intent=" + r.intent + " numReceivers=" + numReceivers + " nextReceiver=" + r.nextReceiver + " state=" + r.state); broadcastTimeoutLocked(false); forceReceive = true; r.state = BroadcastRecord.IDLE; } } if (r.state != BroadcastRecord.IDLE) { if (DEBUG_BROADCAST) Slog.d(TAG, "processNextBroadcast(" + mQueueName + ") called when not idle (state=" + r.state + ")"); return; } if (r.receivers == null || r.nextReceiver >= numReceivers || r.resultAbort || forceReceive) { if (r.resultTo != null) { try { if (DEBUG_BROADCAST) { int seq = r.intent.getIntExtra("seq", -1); Slog.i(TAG, "Finishing broadcast [" + mQueueName + "] " + r.intent.getAction() + " seq=" + seq + " app=" + r.callerApp); } performReceiveLocked(r.callerApp, r.resultTo, new Intent(r.intent), r.resultCode, r.resultData, r.resultExtras, false, false, r.userId); r.resultTo = null; } catch (RemoteException e) { Slog.w(TAG, "Failure [" + mQueueName + "] sending broadcast result of " + r.intent, e); } } if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG"); cancelBroadcastTimeoutLocked(); if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast " + r); addBroadcastToHistoryLocked(r); mOrderedBroadcasts.remove(0); r = null; looped = true; continue; } } while (r == null); int recIdx = r.nextReceiver++;
|
解释基本上代码的注释中,然后贴下 BroadcastRecord 初始化代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| BroadcastRecord(BroadcastQueue _queue, Intent _intent, ProcessRecord _callerApp, String _callerPackage, int _callingPid, int _callingUid, String _requiredPermission, List _receivers, IIntentReceiver _resultTo, int _resultCode, String _resultData, Bundle _resultExtras, boolean _serialized, boolean _sticky, boolean _initialSticky, int _userId) { queue = _queue; intent = _intent; callerApp = _callerApp; callerPackage = _callerPackage; callingPid = _callingPid; callingUid = _callingUid; requiredPermission = _requiredPermission; receivers = _receivers; resultTo = _resultTo; resultCode = _resultCode; resultData = _resultData; resultExtras = _resultExtras; ordered = _serialized; sticky = _sticky; initialSticky = _initialSticky; userId = _userId; nextReceiver = 0; state = IDLE; }
|
APP_RECEIVE 的 state 在静态注册接收器分2种情况讨论那里设置的(文章有点长,有搜索倒回去看看吧)。这个 state 的变化流程是:
IDLE(init) --> APP_RECEIVE(handle) --> IDLE(finish)
然后后面处理下一个接收器就是和前面一样的了,然后直到 mOrderedBroadcasts 中没有待处理的接收器为止。这样就形成了静态注册接收器一个接一个的处理。不过细心的你应该发现了一点,这种实现有个很不靠谱的地方:那就是它要假设上一个接收器正常完成处理。那么如果上一个接收器在处理的过程中挂掉了,或是在处理的时候耗费了大量时间还没处理,是不是串行广播就没法发送到下一个接收器了呢。这个问题我们留在后面再讨论,我们得继续回去把静态注册接收器的第二种情况讨论完,再说这个问题(不然越扯越远,前面说的什么都忘记了)。
PS:头有点晕的回最开始看一下图。
接收器进程还没启动
好现在是比较复杂的情况了,接收器进程还没启动,经过之前 Binder 普通服务篇大致能猜到这里也是发请求给 AMS 去启动指定的进程,然后等待接收器进程启动,再做广播处理。我们先接着看 processNextBroadcast 最后的处理:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| if (DEBUG_BROADCAST) Slog.v(TAG, "Need to start app [" + mQueueName + "] " + targetProcess + " for broadcast " + r); if ((r.curApp=mService.startProcessLocked(targetProcess, info.activityInfo.applicationInfo, true, r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND, "broadcast", r.curComponent, (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0, false)) == null) { Slog.w(TAG, "Unable to launch app " + info.activityInfo.applicationInfo.packageName + "/" + info.activityInfo.applicationInfo.uid + " for broadcast " + r.intent + ": process is bad"); logBroadcastReceiverDiscardLocked(r); finishReceiverLocked(r, r.resultCode, r.resultData, r.resultExtras, r.resultAbort, true); scheduleBroadcastsLocked(); r.state = BroadcastRecord.IDLE; return; } mPendingBroadcast = r; mPendingBroadcastRecvIndex = recIdx;
|
AMS 启动进程的 startProcessLocked 接口这里不再多说,可以去 Binder 普通服务篇的相关章节 看一下。然后后面把当前这一次的 BroadcastRecord 保存到了 mPendingBroadcast 中。这个变量前面有看到过,但是没细说。不过经过 Binder 普通服务篇应该不陌生了,这就是要等候接收器进程启动起来,然后 AMS 接着处理的时候能找回之前等待进程启动的 BroadcastRecord(进程启动最后是会通知 AMS 做一些事情的)。虽然说基本流程我们已经猜得差不多了,但是还是继续把代码看完吧。
上面这里就是 processNextBroadcast 最后的部分了。发送启动接收器进程请求给 AMS 之后,这次的广播处理暂时就完了。然后如果接收器进程正常启动的话那么它的 ActivityThread 会调用 AMS 的 attachApplication:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
| public final void attachApplication(IApplicationThread thread) { synchronized (this) { int callingPid = Binder.getCallingPid(); final long origId = Binder.clearCallingIdentity(); attachApplicationLocked(thread, callingPid); Binder.restoreCallingIdentity(origId); } } ... ... private final boolean attachApplicationLocked(IApplicationThread thread, int pid) { ProcessRecord app; if (pid != MY_PID && pid >= 0) { synchronized (mPidsSelfLocked) { app = mPidsSelfLocked.get(pid); } } else { app = null; } ... ... if (!badApp && isPendingBroadcastProcessLocked(pid)) { try { didSomething = sendPendingBroadcastsLocked(app); } catch (Exception e) { badApp = true; } } if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.uid) { if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app); ensurePackageDexOpt(mBackupTarget.appInfo.packageName); try { thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, compatibilityInfoForPackageLocked(mBackupTarget.appInfo), mBackupTarget.backupMode); } catch (Exception e) { Slog.w(TAG, "Exception scheduling backup agent creation: "); e.printStackTrace(); } } if (badApp) { handleAppDiedLocked(app, false, true); return false; } if (!didSomething) { updateOomAdjLocked(); } return true; }
|
我们来看是怎么检测的:
1 2 3 4 5 6 7 8 9 10 11
| boolean isPendingBroadcastProcessLocked(int pid) { return mFgBroadcastQueue.isPendingBroadcastProcessLocked(pid) || mBgBroadcastQueue.isPendingBroadcastProcessLocked(pid); } public boolean isPendingBroadcastProcessLocked(int pid) { return mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid; }
|
果然前面保存的 mPendingBroadcast 是要等着后面用的。然后我们继续看 AMS 的 sendPendingBroadcastsLocked:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| boolean sendPendingBroadcastsLocked(ProcessRecord app) { boolean didSomething = false; for (BroadcastQueue queue : mBroadcastQueues) { didSomething |= queue.sendPendingBroadcastsLocked(app); } return didSomething; } public boolean sendPendingBroadcastsLocked(ProcessRecord app) { boolean didSomething = false; final BroadcastRecord br = mPendingBroadcast; if (br != null && br.curApp.pid == app.pid) { try { mPendingBroadcast = null; processCurBroadcastLocked(br, app); didSomething = true; } catch (Exception e) { Slog.w(TAG, "Exception in new application when starting receiver " + br.curComponent.flattenToShortString(), e); logBroadcastReceiverDiscardLocked(br); finishReceiverLocked(br, br.resultCode, br.resultData, br.resultExtras, br.resultAbort, true); scheduleBroadcastsLocked(); br.state = BroadcastRecord.IDLE; throw new RuntimeException(e.getMessage()); } } return didSomething; }
|
看到 processCurBroadcastLocked 就松了一口气,后面的流程就和上面静态接收器进程已经启动的情况一样了。好像有了之前的知识(Binder 普通服务篇),这种复杂的情况这里说起来也没多复杂的样子,果然稍微明白 android 的一些设计手法之后很多地方都通用的说。
然后这里补充一个细节,在前面在串行广播处理中有多出错的地方(例如说启动接收器进程失败,或者是接收器为 null 的情况)都会调用
finishReceiverLocked();
scheduleBroadcastsLocked();
这是为了能然广播能够分发下去,当前的出错了就跳过去,然后面的继续执行。
PS:头有点晕的继续回最开始看一下图。
优先级问题
到这里广播的发送、处理流程就差不多说完了。不过前面有说到优先级的问题,这里详细讨论一下。注册篇说到静态注册系统级应用可以在 manifest 的 ‘‘ 设置优先级。这样在收集静态注册接收器的时候优先级高的能排在串行广播列表的前面,就会优先收到广播。但是从上面的处理流程来看,如果广播不是串行的(默认并行),那么动态注册的接收器优先级永远比静态注册的要高(并行处理的我们认为它们同一个时间接到广播)。
这里可以稍微理解下 android 的设计: 虽然说并行广播的本意是让所有接收器一起响应。但是通过前面的分析知道,动态注册的进程都是已经启动起来了的;静态注册的进程基本上都还需要启动。动态切换换字体那篇工作小笔记分析 zygote 的时候知道,启动一个进程在 android 中是十分巨大的一个操作。而且如果静态注册的接收器的进程全都没有启动,那么就需要启动很多个进程。如果同时在后台启动这么多个进程,会造成系统响应严重顿卡。所以 android 广播的处理原则是(并行广播):优先让动态注册的接收器处理广播,然后再让静态注册的接收器串行一个接着一个的处理(这样一次只会启动一个进程)。
然后回来讨论优先级问题。静态注册的接收器按照 manifest 里声明的优先级排序。注册篇说到动态注册的接收器 IntentFilter 有一个 setPriority 可以设置(这个没限制系统应用才能设置),然后动态注册的时候 IntentResolver 也会根据这个优先级排序。前面说在并行广播中(默认)动态注册的接收器优先级肯定排在静态注册的前面,所以动态注册接收器的优先级在并行广播中用处不大。但是在串行广播中,动态注册的接收会合并到静态注册接收器的列表中(前面合有分析合并代码的)。这个时候动态注册接收器的优先级就有用了,合并操作对比动态注册接收器和静态注册接收器的优先级,然后决定动态注册接收器的插入位置(排在静态注册的前面还是后面)。
最后总结一下,前面话太多不直观,来几点:
- 并行广播下,动态注册优先级 > 静态注册,静态注册按自己的优先级排序
- 串行广播下,动态注册和静态注册按各自的优先级一起排序
总结
经过注册篇和本篇的讲解能看得出,广播是集中由 AMS 来处理的:
- 通过 AMS 接口可以动态注册接收器到 AMS(存储在 AMS 中)
- 通过 manifest 声明可以静态注册,由 PMS 扫描(存储在 PMS 中)
- 通过 AMS 发送广播时,AMS 会收集(匹配)自己和 PMS 中的保存的接收器,获取接收器列表(BroadcastRecord)
- 将 BroadcastRecord 放入指定队列(前台 or 后台),执行广播队列(BroadcastQueue)处理
- 广播队列按照优先级将依次(或者并行)广播分发到接收器进程 BroadcastReceiver 回调
前面还有一个讨论串行广播等待处理完成的问题(包括超时问题),鉴于本篇已经很长了,新开一篇来说吧。